/*
 * @Author: hongbin
 * @Date: 2022-09-04 22:26:38
 * @LastEditors: hongbin
 * @LastEditTime: 2022-09-15 19:07:08
 * @Description:home 星球
 */
import THREE, { collideParams } from "../../";
import { loadGlass } from "./Glass";
import { createText, manager } from "../../helper/loaderHelper";
import { MonitorArray, TPlanet } from "../../types";
import { getSize } from "../../helper";
import nx from "../../../assets/img/envTexture/nx.jpg";
import px from "../../../assets/img/envTexture/px.jpg";
import ny from "../../../assets/img/envTexture/ny.jpg";
import py from "../../../assets/img/envTexture/py.jpg";
import pz from "../../../assets/img/envTexture/pz.jpg";
import nz from "../../../assets/img/envTexture/nz.jpg";
import { initFloor } from "./Floor";
import { initStone } from "./Stone";
import { stoneTabletLog } from "./StoneTable";
import { loadBlocks } from "./Blocks";
import { loadPropaganda } from "./Propaganda";
import { loadEmptyIsland } from "./EmptyIsland";
import { loadSpring } from "./Spring";
import { loadRucksack } from "./Rucksack";
import { loadComputer } from "./Computer";

const { homeFloorHeight: floorHeight } = collideParams;
const { Group } = THREE;

// 有体积的即 需要碰撞检测的
const withVolume: MonitorArray<THREE.Object3D> = [];
//整个星球的物体
const objects = new THREE.Group();
/**
 * home中需要逐帧执行的操作
 */
const ticksClip: Array<() => void> = [];
const ticks = () => {
    ticksClip.forEach((tick) => tick());
};

withVolume.push = (...items: typeof withVolume[number][]) => {
    if (typeof withVolume.monitoringChanges === "function") withVolume.monitoringChanges(...items);
    return Array.prototype.push.call(withVolume, ...items);
};

/**
 * 天空 容器
 */
/**
 * home星球
 */
function genSphere() {
    const environmentMapTexture = new THREE.CubeTextureLoader(manager).load([
        nx.src,
        px.src,
        ny.src,
        py.src,
        pz.src,
        nz.src,
    ]);

    const geometry = new THREE.SphereGeometry(550, 32, 32);
    // const geometry = new BoxGeometry(550, 550, 550, 100, 100, 100);
    const material = new THREE.MeshBasicMaterial({
        // ...coastSandRocksTexture,
        envMap: environmentMapTexture,
        side: THREE.DoubleSide,
    });
    const sphere = new THREE.Mesh(geometry, material);
    return sphere;
}

/**
 * 欢迎文字 中英文两版
 * 整段长度太长大于检测距离 后面检测不到 分成几段来实现 这样一段一段检测 也可减小开销
 */
const initWelcomeTextModel = () => {
    const welcome = new Group();
    welcome.position.set(20, 4, 0);
    const wordAddModel = (
        group: THREE.Group,
        words: string[],
        space: number,
        parameters?: Parameters<typeof createText>[1],
        material?: Parameters<typeof createText>[2]
    ) => {
        group.userData.prevX = 0;
        for (const word of words) {
            const wordModel = createText(word, parameters, material);
            const { x } = getSize(wordModel);
            wordModel.position.x = group.userData.prevX;
            group.userData.prevX += x + space;
            group.add(wordModel);
        }
    };
    const english = new Group();
    const englishWords = ["Welcome", "to", "Hongbin's", "3D blog"];
    wordAddModel(english, englishWords, 5, { size: 8 }, { forward: 0xffffff, side: 0xaa1100 });

    const chinese = new Group();
    wordAddModel(chinese, ["欢", "迎", "来", "到", "宏", "斌", "的", "3", "D", "博", "客"], 0);
    chinese.position.set(0, 17, -7.8);
    // guiTestPosition(chinese, 40, "chinese");

    welcome.add(english, chinese);
    return welcome;
};

/**
 * 主线程加载模型
 */
const loadModels = (floor: THREE.Object3D) => {
    const params: [THREE.Object3D, THREE.Object3D[]] = [objects, withVolume];

    const toneTablet = stoneTabletLog(params[0]);
    loadBlocks(params[0], floor);
    loadPropaganda(...params, floorHeight);
    loadGlass(...params);
    loadEmptyIsland(...params);
    loadSpring(...params);
    loadRucksack(params[0]);
    loadComputer(...params, floorHeight);
    withVolume.push(toneTablet);
    objects.add(toneTablet);
};

/**
 * 初始化星球物体
 */
export const init = () => {
    const planet = genSphere();
    planet.name = "home";
    planet.position.y = -20;
    const welcomeText = initWelcomeTextModel();
    const { floor, realFloor } = initFloor();
    initStone((stone) => {
        withVolume.push(stone);
        objects.add(stone);
    });

    home.planet = planet;
    home.mustBeDetected = [realFloor, planet];

    withVolume.push(welcomeText, realFloor);
    objects.add(planet, welcomeText, floor, realFloor);

    loadModels(floor);
};

/**
 * 地下物体 -- 人物万一掉帧到地下获知状态 将人物升起
 */
export const underground = {
    // mesh: new Sphere(new Vector3(0, -1781, 0), 460 * 4),
    needCalculate: (acterYAxisHeight: number) => {
        return acterYAxisHeight < 80;
    },
};

const home = {
    init,
    name: "home",
    withVolume,
    objects,
    ticks,
    underground,
    polarAngle: { min: Math.PI / 2 },
    fallIntoFloor: (upDistance: number) => {
        // velocity.y = Math.abs(velocity.y);
        //! 将本次下降的值反过来 而不是修改velocity.y velocity.y回累减 不是home星球需要的回弹处理
        return -upDistance;
    },
} as TPlanet;

export default home;

objects.position.y = floorHeight;
